home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Sample Code / Newton Sample Code 1.1 / Miscellaneous / Checkbook-3 / checkBook.text < prev    next >
Encoding:
Text File  |  1994-03-09  |  55.8 KB  |  1,987 lines  |  [TEXT/MPS ]

  1. constant kAppSymbol := '|Checkbook:PIETraining|;
  2. constant kAppObject := '["Check", "Checks"];
  3. constant kSoupName := "Checkbook:PIETraining";
  4. constant kCheckFormatSymbol := '|CheckFormat:Checkbook:PIETraining|;
  5. constant kSoupIndexes := '[
  6.     {structure: slot, path: date, type: int}, 
  7.     {structure: slot, path:number, type: int},
  8. ];
  9. constant kAppName := "Checkbook";
  10. constant kMaxApplicationWidth := 800;
  11. constant kMaxApplicationHeight := 1600;
  12.  
  13. DefConst('kMinutesPerDay, 24 * 60);
  14.  
  15.  
  16. InstallScript := func(packageFrame)
  17. begin
  18.     // to set up routing
  19.     routing.(kAppSymbol) := packageFrame.theForm.routingFrame;
  20.     GetRoot().(kCheckFormatSymbol) := BuildContext(packageFrame.theForm.printFormat);   
  21.  
  22.     // To be notified of changes to the soup (including a changed folder)
  23.     AddArraySlot(soupNotify, kSoupName);
  24.     AddArraySlot(soupNotify, kAppSymbol);
  25.  
  26.     // for Find All
  27.     AddArraySlot(findApps, kAppSymbol);
  28.  
  29.     // for IA
  30.     packageFrame.taskTemplateID := RegTaskTemplate(packageFrame.theForm.taskTemplate);
  31. end;
  32.  
  33. RemoveScript := func(packageFrame)
  34. begin
  35.     // remove routing
  36.     RemoveSlot(routing, kAppSymbol);
  37.     RemoveSlot(GetRoot(), kCheckFormatSymbol);
  38.  
  39.     // remove soup name and app symbol from soupNotify array
  40.     local soupNotifyPos := ArrayPos(soupNotify, kAppSymbol, 0, nil);
  41.     ArrayRemoveCount(soupNotify, soupNotifyPos - 1, 2);
  42.  
  43.     // for Find All
  44.     SetRemove(findApps, kAppSymbol);
  45.  
  46.     // for IA
  47.     if packageFrame.taskTemplateID then begin
  48.         UnRegTaskTemplate(packageFrame.taskTemplateID);
  49.         packageFrame.taskTemplateID := nil;
  50.     end;
  51. end;
  52.  
  53. // ---- End Project Data ----
  54.  
  55. // ---- Beginning of Print templates ----
  56.  
  57. // ---- File checkFormat ----
  58. printFormat_checkFormat :=
  59.    {
  60.     printNextPageScript:
  61.       func()
  62.       begin
  63.           return nil;   // we only print one page
  64.       end,
  65.     _proto: protoPrintFormat,
  66.     debug: "printFormat_checkFormat"
  67.    };
  68.  
  69. checkView := /* child of printFormat_checkFormat */
  70.    {viewFlags: 1,
  71.     viewFormat: 336,
  72.     viewBounds: {top: 80, left: 4, right: -4, bottom: 230},
  73.     viewJustify: 48,
  74.     DisplayCheck:
  75.       func(check)
  76.       begin
  77.          //displays a check in the checkView
  78.          SetValue(ckDate, 'text, ShortDateStr(check.date, 0));
  79.          SetValue(ckNumber, 'text, NumberStr(check.number));
  80.          SetValue(ckPayee, 'text, check.payee);
  81.          SetValue(ckAmount, 'text, FormattedNumberStr((check.amount), "%0.2f"));
  82.          SetValue(ckMemo, 'text, check.memo);
  83.       end;,
  84.     viewSetupDoneScript:
  85.       func()
  86.       begin
  87.          :DisplayCheck(fields.target);
  88.       end,
  89.     viewclass: 74,
  90.     debug: "checkView"
  91.    };
  92.  
  93. ckNumber := /* child of checkView */
  94.    {viewBounds: {top: 10, left: -60, right: -2, bottom: 35},
  95.     viewJustify: 8388640,
  96.     viewFlags: 10753,
  97.     _proto: protoInputLine,
  98.     debug: "ckNumber"
  99.    };
  100. // View ckNumber is declared to checkView
  101.  
  102.  
  103.  
  104. ckDate := /* child of checkView */
  105.    {viewBounds: {top: 0, left: -90, right: -2, bottom: 30},
  106.     viewJustify: 8396832,
  107.     viewFlags: 67648033,
  108.     _proto: protoInputLine,
  109.     debug: "ckDate"
  110.    };
  111. // View ckDate is declared to checkView
  112.  
  113.  
  114.  
  115. ckAmount := /* child of checkView */
  116.    {viewBounds: {top: 0, left: 12, right: -97, bottom: 0},
  117.     viewJustify: 8400944,
  118.     viewFlags: 10753,
  119.     _proto: protoInputLine,
  120.     debug: "ckAmount"
  121.    };
  122. // View ckAmount is declared to checkView
  123.  
  124.  
  125.  
  126. amountLabel := /* child of checkView */
  127.    {text: "$",
  128.     viewBounds: {top: 0, left: -10, right: 0, bottom: 0},
  129.     viewJustify: 8402948,
  130.     _proto: protoStaticText,
  131.     debug: "amountLabel"
  132.    };
  133.  
  134.  
  135.  
  136. ckPayee := /* child of checkView */
  137.    {viewBounds: {top: 10, left: 2, right: -2, bottom: 40},
  138.     viewJustify: 8396848,
  139.     viewFlags: 14849,
  140.     _proto: protoInputLine,
  141.     debug: "ckPayee"
  142.    };
  143. // View ckPayee is declared to checkView
  144.  
  145.  
  146.  
  147. payeeLabel := /* child of checkView */
  148.    {text: "Payee",
  149.     viewBounds: {top: -10, left: 0, right: 50, bottom: 15},
  150.     viewJustify: 8398848
  151.     ,
  152.     _proto: protoStaticText,
  153.     debug: "payeeLabel"
  154.    };
  155.  
  156.  
  157.  
  158. ckMemo := /* child of checkView */
  159.    {viewBounds: {top: 0, left: 2, right: -120, bottom: 25},
  160.     viewJustify: 8396848,
  161.     viewFlags: 14849,
  162.     _proto: protoInputLine,
  163.     debug: "ckMemo"
  164.    };
  165. // View ckMemo is declared to checkView
  166.  
  167.  
  168.  
  169. memoLabel := /* child of checkView */
  170.    {text: "Memo",
  171.     viewBounds: {top: -5, left: 0, right: 50, bottom: 10},
  172.     viewJustify: 8398848,
  173.     _proto: protoStaticText,
  174.     debug: "memoLabel"
  175.    };
  176.  
  177.  
  178.  
  179. name := /* child of checkView */
  180.    {text: "Static Text",
  181.     viewBounds: {left: 5, top: 2, right: 120, bottom: 14},
  182.     viewSetupFormScript:
  183.       func()
  184.       begin
  185.          self.text := GetGlobals().userConfiguration.name;
  186.       end,
  187.     _proto: protoStaticText,
  188.     debug: "name"
  189.    };
  190.  
  191.  
  192.  
  193. address := /* child of checkView */
  194.    {text: "Static Text",
  195.     viewBounds: {left: 0, top: 0, right: 0, bottom: 12},
  196.     viewJustify: 8398336,
  197.     viewSetupFormScript:
  198.       func()
  199.       begin
  200.          self.text := GetGlobals().userConfiguration.address;
  201.       end,
  202.     _proto: protoStaticText,
  203.     debug: "address"
  204.    };
  205.  
  206.  
  207.  
  208. cityState := /* child of checkView */
  209.    {text: "Static Text",
  210.     viewBounds: {left: 0, top: 0, right: 0, bottom: 12},
  211.     viewJustify: 8398336,
  212.     viewSetupFormScript:
  213.       func()
  214.       begin
  215.          self.text := GetGlobals().userConfiguration.cityZip;
  216.       end,
  217.     _proto: protoStaticText,
  218.     debug: "cityState"
  219.    };
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226. // ---- End of Print templates ----
  227.  
  228. // ---- File mainlayout.t ----
  229.  
  230. // Before Script for "checkBook"
  231. // Copyright © 1993, 1994 by Apple Computer, Inc.  All rights reserved.
  232.  
  233. nil
  234.  
  235. checkBook :=
  236.    {
  237.     PutAway:
  238.       func(item)
  239.       begin
  240.          // called by beaming to put beamed frame away in the soup
  241.          local newEntry := item.body;
  242.          local theSoup := nil;
  243.       
  244.          CheckThatFolderExists(newEntry);
  245.          if checkbookSoup then
  246.             theSoup := checkbookSoup
  247.          else begin
  248.             theSoup := :RegisterCardSoup(kSoupName,
  249.                kSoupIndexes, kAppSymbol, kAppObject);
  250.             :AddNCKSupportIfNecessary();
  251.          end;
  252.          try
  253.             theSoup:AddToDefaultStore(newEntry);
  254.          onexception |evt.ex| do begin
  255.             if not checkbookSoup then
  256.                :UnRegisterCardSoup(kSoupName);
  257.             Rethrow();
  258.          end;
  259.          if not checkbookSoup then
  260.             :UnRegisterCardSoup(kSoupName);
  261.          BroadcastSoupChange(kSoupName);
  262.       end,
  263.     DisplayOverview:
  264.       func()
  265.       begin
  266.          if currentView = checkView then
  267.             checkView:Hide();
  268.          if call kViewIsOpenFunc with (overview) then begin
  269.             // fill in new data before displaying to avoid ugly redraw.
  270.             overview:DisplayFromCursor();
  271.             overview:Show();
  272.          end else
  273.             overview:Open();
  274.       end,
  275.     taskTemplate:
  276.        // used by IA. See InstallScript in Project Data
  277.       
  278.       DefConst('kPayAction, {
  279.             name: "pay action",
  280.             isa: 'dyna_user_action,
  281.             lexicon: ["pay", "write check"],
  282.          }
  283.       );
  284.       
  285.       {
  286.          value: "pay task",
  287.          isa: 'task_template,
  288.          primary_act: kPayAction,
  289.          preconditions: ['action, 'who, 'whichCompany, 'when, 'amount],
  290.          signature: [kPayAction, 'person, 'company, 'date, 'number],
  291.             // The post parse method is called as a method of the taskTemplate
  292.             // It calls an application method with the taskTemplate as a parameter.
  293.          postParse: func() GetRoot().(kAppSymbol):PostParseCommand(self),
  294.       },
  295.     AddNCKSupportIfNecessary:
  296.       func()
  297.       begin
  298.          local soup := GetStores()[0]:GetSoup("Directory");
  299.          local q := Query(soup, 
  300.             {type: 'index, indexPath: 'soup, startKey: kSoupName, endTest: func(item) NOT StrEqual(item.soup, kSoupName)});
  301.             
  302.          // if upgrading is important, should check version number
  303.          if not q:Entry() then begin
  304.             local nckMeta := Clone(nckMetaData);
  305.       
  306.             nckMeta.soup := kSoupName;
  307.             nckMeta.name := kAppName;
  308.             soup:Add(nckMeta);
  309.          end;
  310.       end,
  311.     viewSetupDoneScript:
  312.       func()
  313.       begin
  314.          if openToOverview then
  315.             :DisplayOverview();
  316.          else 
  317.             :DisplayCurrentCheck();
  318.       end,
  319.     GetCheckAsText:
  320.       func(check)
  321.       begin
  322.          ShortDateStr(check.date, 0) && check.payee && FormattedNumberStr(check.amount, "%0.2f")
  323.       end,
  324.     viewFormat: 590161,
  325.     UndoDuplicateCheck:
  326.       func(duplicatedCheck)
  327.       begin
  328.          EntryRemoveFromSoup(duplicatedCheck);
  329.          BroadcastSoupChange(kSoupName);   // soupChanged knows how to redisplay
  330.       end,
  331.     viewQuitScript:
  332.       func()
  333.       begin
  334.          if currentView = checkView then begin
  335.             checkView:SaveCheck();
  336.             openToOverview := nil;
  337.          end else
  338.             openToOverview := true;
  339.       
  340.          if target = nil and checkBookCursor <> nil then
  341.             target := checkBookCursor:Entry();
  342.       
  343.          :UnRegisterCardSoup(kSoupName);
  344.       
  345.          // nil out slots with run-time values
  346.          checkBookSoup := nil;   
  347.          currentView := nil;
  348.          checkBookCursor := nil;
  349.          target := nil;
  350.          
  351.          ClearUndoStacks();  // any undo actions added will "grab" the card.
  352.       end
  353.       
  354.       /*
  355.           Here is some code you can use to make sure you've NIL'd out all
  356.           relavant data from an app's base view after closing:
  357.           
  358.           call func(view) begin
  359.               foreach slot, value in view do begin
  360.                   write(slot);
  361.                   write($:);
  362.                   write($\t);
  363.                   if value = view._parent then print("parent");
  364.                   else if value = view._proto then print("proto");
  365.                   else if value = GetRoot() then print("root");
  366.                   else if value = view then print("self");
  367.                   else print(value);
  368.               end;
  369.           end with (GetRoot().(kAppSymbol))
  370.           
  371.       */,
  372.     appAll: "All Checks" // used by Filing,
  373.     checkBookSoup:
  374.       nil   // contains the checkbook union soup. Inited in viewSetupFormScript,
  375.     target:
  376.       nil // points to current soup entry. Maintained by
  377.           // overview.viewSetupDoneScript and checkView.DisplayBook,
  378.     RegisterCardSoup:
  379.       func(soupName, soupIndexes, appSymbol, appObject)
  380.       begin
  381.          // returns a union soup for your app to use
  382.          
  383.          // first check for system provided function
  384.          if functions.RegisterCardSoup then
  385.             return RegisterCardSoup(soupName, soupIndexes, appSymbol, appObject);
  386.          
  387.          CreateAppSoup(soupName, soupIndexes, EnsureInternal([appSymbol]),
  388.            EnsureInternal(appObject));
  389.          
  390.          // ensure your soup will exists on stores which later become available.
  391.          AddArraySlot(cardSoups, soupName);
  392.          AddArraySlot(cardSOups, soupIndexes);
  393.       
  394.          // ensure your soup exists on all currently available stores
  395.          local store;
  396.          foreach store in GetStores() do
  397.             if not store:IsReadOnly() and not store:HasSoup(soupName) then
  398.                store:CreateSoup(soupName, soupIndexes);
  399.       
  400.          return GetUnionSoup(soupName);
  401.       end,
  402.     FolderChanged:
  403.       func(soupName, oldLabel, newLabel)
  404.       begin
  405.          // the application may not be open when this message is 
  406.          // sent. Change all oldLabels in the soup to newLabel
  407.       
  408.          local soup := GetUnionSoup(kSoupName);
  409.          if soup then begin   // could have changed folders before ever running the app.
  410.             local cursor := query(soup, {type: 'index,
  411.                validTest: func(entry)
  412.                begin
  413.                   return entry.labels = oldLabel;
  414.                end
  415.             });
  416.       
  417.             // change the labels of each entry in the cursor to newLabel
  418.             local e := cursor:Entry();
  419.             while e do begin
  420.                e.labels := newLabel;
  421.                EntryChange(e);
  422.                e := cursor:Next();
  423.             end;
  424.             BroadcastSoupChange(kSoupName);
  425.          end;
  426.          if folderTab then
  427.             folderTab:UpdateFilter(oldLabel, newLabel);   // redraw the filter
  428.       end,
  429.     viewFlags: 5,
  430.     DisplayCheck:
  431.       func(check)
  432.       begin
  433.          // Opens the checkView (if necessary) and displays check.
  434.       
  435.          // make sure cursor points to the displayed check
  436.          if checkBookCursor:Entry() <> check then
  437.             checkBookCursor:Goto(check);
  438.       
  439.          if currentView <> checkView then
  440.          begin
  441.             if currentView = overView then
  442.                overview:Hide();
  443.             if not call kViewIsOpenFunc with (checkView) then
  444.                checkView:Open();         // should only happen once
  445.          end;
  446.       
  447.          checkView:DisplayCheck(check);
  448.          if currentView <> checkView then
  449.             checkView:Show();      // show after changing contents of the view
  450.       end,
  451.     DeleteActionScript:
  452.       func(entryToDelete, targetView)
  453.       begin
  454.          // called when the user chooses Duplicate from the routing action button
  455.       
  456.          if not entryToDelete then
  457.             GetRoot():SysBeep();
  458.          else begin
  459.             checkView:Delete('DeleteCheck, [entryToDelete]);
  460.             AddUndoAction('UndoDeleteCheck, [entryToDelete]);
  461.          end;
  462.       end,
  463.     Redisplay:
  464.       func()
  465.       begin
  466.          // displays the current check, if possible. Otherwise,
  467.          // goes to the first check in the cursor and displays it.
  468.          if target and target <> 'deleted and IsSoupEntry(target) then
  469.             currentView:Dirty() // redisplay. Something might have changed.
  470.          else begin
  471.             checkBookCursor:Reset();
  472.             if currentView = checkView then begin
  473.                if not checkBookCursor:Entry() then begin
  474.                   // no checks in this folder
  475.                   :DisplayOverview();
  476.                end else
  477.                   :DisplayCurrentCheck();
  478.             end else
  479.                overview:DisplayFromCursor();
  480.          end;
  481.       end,
  482.     viewBounds: {top: 3, left: 0, right: 234, bottom: 335},
  483.     DateFind:
  484.       func(findTime, comparison, results, scope, statusForm)
  485.       begin
  486.          if statusForm then
  487.             statusForm:SetStatus("Searching in" && kAppName & $\u2026); // 2026 is unicode …
  488.       
  489.          local soup := GetUnionSoup(kSoupName);
  490.          if soup then begin   // the app could never have run
  491.             // look for all entries with text containing what
  492.             local cursor := Query(soup, {type: 'index, 
  493.                validTest: if comparison = 'dateBefore then
  494.                   func(entry)
  495.                   begin
  496.                      return entry.date < findTime;
  497.                   end
  498.                else
  499.                   func(entry)
  500.                   begin
  501.                      return entry.date > findTime;
  502.                   end
  503.             });
  504.       
  505.             if cursor:Entry() then begin
  506.                local ourResult := {
  507.                   _proto: GetRoot().soupFinder,
  508.                   owner: self,
  509.                   title: kAppName,
  510.                   findType: comparison,
  511.                   findTime: findTime,
  512.                   cursor: cursor,
  513.                };
  514.                AddArraySlot(results, ourResult);
  515.             end;
  516.          end;
  517.       end,
  518.     AddCheckToSOup:
  519.       func(newCheck)
  520.       begin
  521.          try
  522.             checkbookSoup:AddToDefaultStore(newCheck);
  523.          onexception |evt.ex| do begin
  524.             // catch the exception so we return cleanly. A message will
  525.             // already have been presented. We want the New button to unhilite.
  526.          end;
  527.       
  528.          if not checkbookCursor:Goto(newCheck) then begin
  529.             // not in this folder. Change to "All" folder so we can see it
  530.             folderTab:UpdateFilter(labelsFilter, '_all);
  531.          end;
  532.          :DisplayCheck(newCheck);
  533.       end,
  534.     appObject: kAppObject // used by Filing,
  535.     FilingChanged:
  536.       func()
  537.       begin
  538.          :Redisplay();
  539.       end,
  540.     CreateNewCheck:
  541.       func()
  542.       begin
  543.          // creates a new check, adds it to the soup, and displays it.
  544.       
  545.          local newCheck := Clone(defaultCheck);
  546.          newCheck.date := Time();
  547.          newCheck.number := :HighestCheckNumber() + 1;
  548.       
  549.          :AddCheckToSoup(newCheck);
  550.       end,
  551.     DisplayCurrentCheck:
  552.       func()
  553.       begin
  554.          // displays the check the cursor points to
  555.          // if there isn't anything in the cursor, display the overview
  556.          local entry := checkbookCursor:Entry();
  557.          if not entry then
  558.             checkbookCursor:Reset();
  559.          entry := checkbookCursor:Entry();
  560.          if not entry then
  561.             :DisplayOverview();
  562.          else
  563.             :DisplayCheck(entry);
  564.       end,
  565.     FilterChanged:
  566.       func()
  567.       begin
  568.          :Redisplay();
  569.       end,
  570.     labelsFilter: nil // current folder on display. Used by filing.,
  571.     routingFrame:
  572.       {   // used by InstallScript to set up routing action button
  573.          print: {
  574.             title: "Print Check",
  575.             routeForm: 'printSlip,
  576.             formats: [kCheckFormatSymbol],
  577.          },
  578.       
  579.          fax: {
  580.             title: "Fax",
  581.             routeForm: 'faxSlip,
  582.             formats: [kCheckFormatSymbol],
  583.          },
  584.       
  585.          beam: {
  586.             title: "Beam",
  587.             routeForm: 'zapSlip, 
  588.           },
  589.       
  590.          mail: {
  591.             title: "Mail",
  592.             routeForm: 'mailSlip,
  593.             formats: [kCheckFormatSymbol],
  594.          },
  595.          separator: nil,
  596.       
  597.          delete: {
  598.             title: "Delete",
  599.             routeScript: 'DeleteActionScript, 
  600.          },
  601.       
  602.          duplicate: {
  603.             title: "Duplicate",
  604.             routeScript: 'DuplicateActionScript,
  605.          },
  606.         
  607.          card: ROM_cardAction,
  608.       };,
  609.     ShowFoundItem:
  610.       func(entry, finder)
  611.       begin
  612.          if not checkbookCursor:Goto(entry) then begin
  613.             // not in this folder. Change to "All" folder so we can see it
  614.             folderTab:UpdateFilter(labelsFilter, '_all);
  615.          end;
  616.          :DisplayCheck(entry);
  617.       end,
  618.     viewScrollDownScript:
  619.       func()
  620.       begin
  621.          // let the current view handle it
  622.          currentView:viewScrollDownScript();
  623.       end,
  624.     viewOverviewScript:
  625.       func()
  626.       begin
  627.          // called when the user clicks the overview button
  628.       
  629.          if currentView = overview then
  630.             // If the overview is open, and there is something to display,
  631.             // display it.
  632.             if not checkbookCursor:Entry() then
  633.                GetRoot():SysBeep();
  634.             else
  635.                :DisplayCurrentCheck()
  636.          else begin
  637.             // otherwise, switch to the overview
  638.             :DisplayOverview();
  639.          end;
  640.       end,
  641.     checkBookCursor:
  642.       nil // a cursor available to the whole application that points to checkBookSoup entries
  643.     ,
  644.     PostParseCommand:
  645.       func(taskTemplate)
  646.       begin
  647.          // called in response to the "Pay" request from IA
  648.       
  649.          local applicationWasOpen := (call kViewIsOpenFunc with (self)) <> nil;
  650.          :Open();   // we might be closed;
  651.          
  652.          local newCheck := Clone(defaultCheck);
  653.          newCheck.number := :HighestCheckNumber() + 1;
  654.          newCheck.date := Time();
  655.       
  656.          for i := 0 to Length(taskTemplate.input) - 1 do begin
  657.             local template := taskTemplate.input[i];
  658.             if Isa(template, 'person) or isa(template, 'company) then
  659.                newCheck.payee := taskTemplate.phrases[i];
  660.             else if Isa(template, 'parsed_number) then
  661.                newCheck.amount := StringToNumber(template.value);
  662.             else if Isa(template, 'date) then begin
  663.                newCheck.date := StringToDate(template.value);
  664.                newCheck.date := newCheck.date - newCheck.date MOD kMinutesPerDay;
  665.             end;
  666.          end;
  667.          local assistView := BuildContext(pt_assistDialogProto);
  668.       
  669.          assistView:Open();
  670.          assistView:DisplayEntry(newCheck, applicationWasOpen);
  671.       
  672.          GetRoot().assistant:Close();   // close the IA slip
  673.       
  674.       end,
  675.     appSymbol: kAppSymbol   // needed for routing and filing,
  676.     title: "Checkbook",
  677.     nckMetaData:
  678.       {
  679.           soup: nil,     // added at runtime
  680.           name: nil,    // added at runtime
  681.           version: 1,
  682.       
  683.           defaultDefinitions: {
  684.              textNumber: {label: "Check No.", path: 'number, size: 5, type: 'integer},
  685.              textDate: {label: "Date:", path: 'date, size: 8, type: 'string},
  686.              textPayee: {label: "To:", path: 'payee, size: 20, type: 'string},
  687.              textAmount: {label: "Amount:", path: 'amount, size: 10, type: 'real},
  688.            },
  689.       
  690.           displayInfo: [
  691.              'textNumber,
  692.              'textDate,
  693.              'textPayee,
  694.              'textAmount,
  695.          ],
  696.       
  697.           editInfo: [
  698.              'textNumber,
  699.              'textDate,
  700.              'textPayee,
  701.              'textAmount,
  702.          ],
  703.       
  704.          exportInfo: [
  705.              'textNumber,
  706.              'textDate,
  707.              'textPayee,
  708.              'textAmount,
  709.          ],
  710.       
  711.          import: func(textFrame)
  712.          begin
  713.             // this routine is called from within Newton Connection
  714.             // Therefore, don't use any routines from the application. This
  715.             // routine must be standalone.
  716.             // It converts a textual representation of a check to a soup entry.
  717.             local soupFrame;
  718.             local value;
  719.       
  720.             if textFrame.originalFrame then
  721.                soupFrame := textFrame.originalFrame;
  722.             else
  723.                soupFrame := {
  724.                   payee: "",
  725.                   memo: "",
  726.                   amount: 0.0,
  727.                   number: 0,
  728.                   date: 0
  729.                };
  730.             soupFrame.payee := textFrame.textPayee;
  731.             value := StringToNumber(textFrame.textAmount);
  732.             if value then
  733.                soupFrame.amount := value;
  734.             value := Floor(StringToNumber(textFrame.textNumber));
  735.             if value then
  736.                soupFrame.number := value;
  737.             value := StringToDate(textFrame.textDate);
  738.             if value then
  739.                soupFrame.date := value - value MOD kMinutesPerDay;
  740.       
  741.             return soupFrame;
  742.          end,
  743.       
  744.           export: func(soupFrame)
  745.             begin
  746.             local textFrame := {originalFrame: soupFrame};
  747.          
  748.             textFrame.textNumber := 
  749.                if soupFrame.number then
  750.                   SPrintObject(soupFrame.number)
  751.                else
  752.                   "";
  753.       
  754.             textFrame.textDate :=
  755.                if soupFrame.date then
  756.                   ShortDateStr(soupFrame.date, 0);
  757.                else
  758.                   "";
  759.       
  760.             textFrame.textPayee :=
  761.                if soupFrame.payee then
  762.                   soupFrame.payee;
  763.                else
  764.                   "";
  765.       
  766.             textFrame.textAmount :=
  767.                if soupFrame.amount then
  768.                   SPrintObject(soupFrame.amount);
  769.                else
  770.                   "";
  771.       
  772.             return textFrame;
  773.           end,
  774.       },
  775.     HighestCheckNumber:
  776.       func()
  777.       begin
  778.          local cursor := Query(checkBookSoup, {type: 'index, indexPath: 'number});
  779.       /*
  780.          cursor:GotoKey({number: 999999});   // larger than any possible check number
  781.          cursor:Prev();   // now points at the highest number
  782.          local entry := cursor:Entry();
  783.       */
  784.          while cursor:Next() do begin
  785.          end;
  786.          local entry := cursor:Prev();
  787.          if entry and entry.number then
  788.             return entry.number;
  789.          else
  790.             return 0;
  791.       end,
  792.     Find:
  793.       func(what,results,scope,statusForm)
  794.       begin
  795.       
  796.          if statusForm then
  797.             statusForm:SetStatus("Searching in" && kAppName & $\u2026); // 2026 is unicode …
  798.       
  799.          local soup := GetUnionSoup(kSoupName);
  800.          if soup then begin   // the app could never have run
  801.              // look for all entries with text containing what
  802.              local cursor := Query(soup, {type: 'text, text: what});
  803.       
  804.              if cursor:Entry() then begin
  805.                  local ourResult := {
  806.                      _proto: GetRoot().soupFinder,
  807.                      owner: self,
  808.                      title: kAppName,
  809.                      findType: 'text,
  810.                      findWords: [what],
  811.                      cursor: cursor,
  812.                  };
  813.                  AddArraySlot(results, ourResult);
  814.              end;
  815.          end;
  816.       end,
  817.     viewScrollUpScript:
  818.       func()
  819.       begin
  820.          // let the current view handle it
  821.          currentView:viewScrollUpScript();
  822.       end,
  823.     declareSelf: 'base,
  824.     viewSetupFormScript:
  825.       func()
  826.       begin
  827.          targetView := self;   // used by Routing and Filing
  828.       
  829.          checkBookSoup := :RegisterCardSoup(kSoupName, kSoupIndexes, kAppSymbol, kAppObject);
  830.       
  831.          :AddNCKSupportIfNecessary();
  832.       
  833.          // create a cursor which takes into account labelsFilter (for filing)
  834.          checkBookCursor := Query(checkBookSoup, {
  835.             type: 'index, 
  836.             indexPath: 'date,
  837.             validTest: func(entry) begin
  838.                return labelsFilter = '_all or
  839.                   entry.labels = labelsFilter;
  840.             end,
  841.          });   
  842.          
  843.          // generate random data if no checks exist
  844.          if not CheckBookCursor:Entry() then begin
  845.             // arrays used to generate random payees and memos
  846.          
  847.             local randomPayees := [
  848.                "Julie McKeehan",
  849.                "Computer Literacy",
  850.                "Neil Rhodes",
  851.                "Apple Computer"
  852.             ];
  853.                local randomMemos := [
  854.                "lunch",
  855.                "equipment",
  856.                "gift",
  857.                "Inv# 56790",
  858.             ];
  859.             for i := 1 to 20 do begin
  860.                   local randomCheck := {
  861.                       payee: randomPayees[Random(0, Length(randomPayees)-1)],
  862.                       memo: randomMemos[Random(0, Length(randomMemos)-1)],
  863.                       date:    Time() - Random(0, 10) * kMinutesPerDay,
  864.                       number:  100 + i,
  865.                       amount:  Random(100,500000)/100.00,  //32.15, for instance
  866.                   };
  867.                    randomCheck.date := randomCheck.date - randomCheck.date MOD kMinutesPerDay;
  868.                checkBookSoup:AddToDefaultStore(randomCheck);
  869.             end;
  870.          end;
  871.       
  872.          // resize to fit this screen. Inset by one on top, left, and right
  873.          local params := GetAppParams();
  874.          self.viewBounds := RelBounds(
  875.             params.appAreaLeft + 1,
  876.             params.appAreaTop + 1,
  877.             Min(kMaxApplicationWidth, params.appAreaWidth - 2),
  878.             Min(kMaxApplicationWidth, params.appAreaHeight - 1)
  879.          );
  880.          
  881.          // Open in the same state as when closed
  882.          if target and not checkBookCursor:Goto(target)
  883.             then checkBookCursor:Reset();
  884.       end
  885.       ,
  886.     DuplicateActionScript:
  887.       func(entryToDuplicate, targetView)
  888.       begin
  889.          // called when the user chooses Duplicate from the routing action button
  890.       
  891.          if not entryToDuplicate then 
  892.             GetRoot():SysBeep()
  893.          else begin
  894.             local newEntry := EntryCopy(entryToDuplicate, checkBookSoup);
  895.                
  896.             :DisplayCheck(newEntry);
  897.             AddUndoAction('UndoDuplicateCheck, [newEntry]);
  898.          end;
  899.       end,
  900.     currentView:
  901.       nil    // points to the checkView or the overview depending 
  902.             // on which one is currently open,
  903.     UndoDeleteCheck:
  904.       func(deletedCheck)
  905.       begin
  906.          checkBookSoup:AddToDefaultStore(deletedCheck);
  907.          if checkbookCursor:Clone():Goto(deletedCheck) then
  908.             :DisplayCheck(deletedCheck);
  909.          // else leave the display alone
  910.       end,
  911.     printFormat:
  912.       {  // used for printing/faxing/mailing. See InstallScript
  913.       
  914.          // title that shows up in the Format picker
  915.          // in the print or fax slip
  916.          title: kAppName,
  917.       
  918.          // this could be a symbol for an auxilliary
  919.          // information slip. See the auxForm sample code
  920.          auxForm: nil,
  921.           
  922.          // symbol for a script that is called by
  923.          // mail for a text only message to send
  924.          textScript: 'GetTextForMail,
  925.       
  926.          // true if the user can attach a real
  927.          // frame to the mail
  928.          attachment: true,
  929.       
  930.          // a proto to get a coverPage for free!
  931.          _proto: ROM_coverPageFormat,
  932.       
  933.          // the main format used for each page of
  934.          // a print or fax output.
  935.          mainFormat: printFormat_checkFormat,
  936.       },
  937.     SetupRoutingSlip:
  938.       func(fields)
  939.       begin
  940.          // called for routing when beaming/mailing
  941.          fields.target := target;
  942.          fields.title := :GetCheckAsText(target);
  943.       end,
  944.     viewclass: 74,
  945.     FindSoupExcerpt:
  946.       func(entry, finder)
  947.       begin
  948.          if finder.findType = 'dateBefore or 
  949.             finder.findType = 'dateAfter then
  950.             return GetRoot().(kAppSymbol):GetCheckAsText(entry); 
  951.          else // call inherited version of FindSoupExcerpt
  952.             :Parent():FindSoupExcerpt(entry, finder);
  953.       end,
  954.     defaultCheck:
  955.       {   // check which is cloned as a new check is created.
  956.          payee:   "",
  957.          memo: "",
  958.          amount: 0.00,
  959.          number: 101,
  960.          date: 0,
  961.       },
  962.     openToOverview:
  963.       true // true if overview should display on open, nil if checkView should display
  964.     ,
  965.     debug: "checkBook",
  966.     targetView:
  967.       nil // used by Routing and Filing. Initialized in viewSetupFormScript,
  968.     GetTextForMail:
  969.       func(fields, check)
  970.       begin
  971.          // called by routing when user requests text version of message
  972.          text := "Check #" & check.number & "\n";
  973.          text := text & "To:" && check.payee & "\n";
  974.          text := text & "Amount:" && FormattedNumberStr(check.amount, "%0.2f") & "\n";
  975.          text := text & "Memo:" && check.memo & "\n";
  976.          text := text & "Date:" && ShortDateStr(check.date, 0);
  977.          return text;
  978.       end,
  979.     viewSetupChildrenScript:
  980.       func()
  981.       begin
  982.          // open the view which was open when we closed.
  983.          if openToOverview then
  984.             overview.viewFlags := BOR(overview.viewFlags, vVisible);
  985.          else
  986.             checkView.viewFlags := BOR(checkView.viewFlags, vVisible);
  987.       end,
  988.     soupChanged:
  989.       func(theSoupName)
  990.       begin
  991.          if call kViewIsOpenFunc with (self) then  // the application is open
  992.             :Redisplay()
  993.       end,
  994.     UnRegisterCardSoup:
  995.       func(soupName)
  996.       begin
  997.          // first check for system provided function
  998.          if functions.UnRegisterCardSoup then
  999.             return UnRegisterCardSoup(soupName);
  1000.       
  1001.          local pos := ArrayPos(cardSoups, soupName, 0, func(x, y) 
  1002.             ClassOf(y) = 'String and StrEqual(x, y));
  1003.          if pos then
  1004.             ArrayRemoveCount(cardSoups, pos, 2);
  1005.       end
  1006.    };
  1007.  
  1008.  
  1009. // Before Script for "folderTab"
  1010. // Copyright © 1993, 1994 by Apple Computer, Inc.  All rights reserved.
  1011.  
  1012. nil
  1013.  
  1014. folderTab := /* child of checkBook */
  1015.    {_proto: protoFolderTab, debug: "folderTab"};
  1016. // View folderTab is declared to checkBook
  1017.  
  1018.  
  1019.  
  1020.  
  1021. // Before Script for "_view000"
  1022. // Copyright © 1993, 1994 by Apple Computer, Inc.  All rights reserved.
  1023.  
  1024. nil
  1025.  
  1026. _view000 := /* child of checkBook */ {_proto: protoStatus};
  1027.  
  1028.  
  1029. // Before Script for "_view001"
  1030. // Copyright © 1993, 1994 by Apple Computer, Inc.  All rights reserved.
  1031.  
  1032. nil
  1033.  
  1034. _view001 := /* child of _view000 */ {_proto: protoActionButton};
  1035.  
  1036.  
  1037.  
  1038.  
  1039. // Before Script for "_view002"
  1040. // Copyright © 1993, 1994 by Apple Computer, Inc.  All rights reserved.
  1041.  
  1042. nil
  1043.  
  1044. _view002 := /* child of _view000 */
  1045.    {viewBounds: {left: -23, top: 2, right: -6, bottom: 15},
  1046.     _proto: protoFilingButton
  1047.    };
  1048.  
  1049.  
  1050.  
  1051.  
  1052. // Before Script for "newButton"
  1053. // Copyright © 1993, 1994 by Apple Computer, Inc.  All rights reserved.
  1054.  
  1055. nil
  1056.  
  1057. newButton := /* child of _view000 */
  1058.    {text: "New",
  1059.     buttonClickScript:
  1060.       func()
  1061.       begin
  1062.          base:CreateNewCheck();
  1063.       end,
  1064.     viewBounds: {left: 25, top: 2, right: 55, bottom: 15},
  1065.     _proto: protoTextButton,
  1066.     debug: "newButton"
  1067.    };
  1068.  
  1069. // After Script for "newButton"
  1070. thisView := newButton;
  1071. // set the bounds of the button so that it is to the right
  1072. // of the clock and the correct height for the status bar
  1073.  
  1074. // NOTE: this is the first "real" button, so argument to the
  1075. // ButtonBounds function MUST be negative
  1076. thisView.viewBounds := ButtonBounds(-(thisView.viewBounds.right - thisView.viewBounds.left));
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082. // ---- File checkView.t ----
  1083. checkView := /* child of checkBook */
  1084.    {viewFlags: 0,
  1085.     viewFormat: 336,
  1086.     viewBounds: {top: 80, left: 4, right: -4, bottom: 230},
  1087.     viewJustify: 48,
  1088.     DisplayCheck:
  1089.       func(check)
  1090.       begin
  1091.          //displays a check in the checkView
  1092.       
  1093.          // save the previous entry
  1094.          if currentCheck then
  1095.             :SaveCheck();
  1096.       
  1097.          SetValue(ckDate, 'text, ShortDateStr(check.date, 0));
  1098.          SetValue(ckNumber, 'text, NumberStr(check.number));
  1099.          SetValue(ckPayee, 'text, check.payee);
  1100.          SetValue(ckAmount, 'text, FormattedNumberStr((check.amount), "%0.2f"));
  1101.          SetValue(ckMemo, 'text, check.memo);
  1102.       
  1103.          self.currentCheck := check;
  1104.          target := check; // current soup entry. Used for routing and filing.
  1105.                           // target is a slot in the base view.
  1106.       end;,
  1107.     currentCheck: nil,
  1108.     SaveCheck:
  1109.       func()
  1110.       begin
  1111.           if currentCheck then
  1112.           begin
  1113.               // reads the information from the input lines into the current
  1114.               // check and saves the entry into the soup.
  1115.               
  1116.               currentCheck.payee := ckPayee.text;
  1117.               currentCheck.memo := ckMemo.text;
  1118.               
  1119.               // StringToNumber can return NIL if the string is not a valid number
  1120.               // It would be a bad idea to have a NIL amount, or number.
  1121.               local value := StringToNumber(ckNumber.text);
  1122.               if value then begin
  1123.                  // RIntToL converts a real to an integer
  1124.                  currentCheck.number := RIntToL(value);
  1125.               end;
  1126.               
  1127.               value := StringToNumber(ckAmount.text);
  1128.               if value then
  1129.                  currentCheck.amount := value;
  1130.               
  1131.               // StringToDate takes into account the current time.
  1132.               // thus, if the current time is 7:03 PM
  1133.               // StringToDate("5/5/93") returns number of minutes to 7:03 PM
  1134.               // on 5/5/93.
  1135.               // StringToDate can return NIL for an invalid date.
  1136.               value := StringToDate(ckDate.text);
  1137.               if value then
  1138.                  // convert to 12:00 AM by truncating any minutes beyond 12 AM
  1139.                  currentCheck.date := value - value mod kMinutesPerDay;
  1140.               
  1141.               EntryChange(currentCheck);   // save in the soup
  1142.               self.currentCheck := nil;
  1143.           end;
  1144.       end,
  1145.     viewEffect: 1023009,
  1146.     viewShowScript:
  1147.       func()
  1148.       begin
  1149.          currentView := self;   // currentView is in the base view
  1150.       end,
  1151.     viewHideScript:
  1152.       func()
  1153.       begin
  1154.          :SaveCheck();
  1155.       end,
  1156.     DeleteCheck:
  1157.       func(entryToDelete)
  1158.       begin
  1159.          EntryRemoveFromSoup(entryToDelete);
  1160.          currentCheck := target := nil;
  1161.          checkBookCursor:Next();
  1162.          if not checkBookCursor:Entry() then // they deleted the last entry in the soup
  1163.             checkBookCursor:Prev();
  1164.          if not checkBookCursor:Entry() then begin// there are no more books in the soup
  1165.             GetRoot().(kAppSymbol):DisplayOverview();
  1166.          end
  1167.          else
  1168.             GetRoot().(kAppSymbol):DisplayCurrentCheck();
  1169.       end     ,
  1170.     viewScrollDownScript:
  1171.       func()
  1172.       begin
  1173.          local cursor := checkbookCursor;
  1174.       
  1175.          cursor:Next();
  1176.       
  1177.          local entry := cursor:Entry();
  1178.          if entry = nil then begin
  1179.             GetRoot():SysBeep();   
  1180.             cursor:Prev();
  1181.          end else begin
  1182.             local bounds := :LocalBox();
  1183.             :SlideEffect(- (bounds.bottom - bounds.top),
  1184.                0,
  1185.                scrollDownSound,
  1186.                'DisplayCheck,
  1187.                [entry]
  1188.             );
  1189.          end;
  1190.       end,
  1191.     viewScrollUpScript:
  1192.       func()
  1193.       begin
  1194.          local cursor := checkbookCursor;
  1195.       
  1196.          cursor:Prev();
  1197.       
  1198.          local entry := cursor:Entry();
  1199.          if entry = nil then begin
  1200.             GetRoot():SysBeep();   
  1201.             cursor:Next();
  1202.          end else begin
  1203.             local bounds := :LocalBox();
  1204.             :SlideEffect(bounds.bottom - bounds.top,
  1205.                0,
  1206.                scrollUpSound,
  1207.                'DisplayCheck,
  1208.                [entry]
  1209.             );
  1210.          end;
  1211.       end,
  1212.     viewclass: 74,
  1213.     debug: "checkView"
  1214.    };
  1215. // View checkView is declared to checkBook
  1216.  
  1217. ckNumber := /* child of checkView */
  1218.    {viewBounds: {top: 10, left: -60, right: -2, bottom: 35},
  1219.     viewJustify: 8388640,
  1220.     viewFlags: 10753,
  1221.     _proto: protoInputLine,
  1222.     debug: "ckNumber"
  1223.    };
  1224. // View ckNumber is declared to checkView
  1225.  
  1226.  
  1227.  
  1228. ckDate := /* child of checkView */
  1229.    {viewBounds: {top: 0, left: -90, right: -2, bottom: 30},
  1230.     viewJustify: 8396832,
  1231.     viewFlags: 67648033,
  1232.     _proto: protoInputLine,
  1233.     debug: "ckDate"
  1234.    };
  1235. // View ckDate is declared to checkView
  1236.  
  1237.  
  1238.  
  1239. ckAmount := /* child of checkView */
  1240.    {viewBounds: {top: 0, left: 12, right: -97, bottom: 0},
  1241.     viewJustify: 8400944,
  1242.     viewFlags: 10753,
  1243.     _proto: protoInputLine,
  1244.     debug: "ckAmount"
  1245.    };
  1246. // View ckAmount is declared to checkView
  1247.  
  1248.  
  1249.  
  1250. amountLabel := /* child of checkView */
  1251.    {text: "$",
  1252.     viewBounds: {top: 0, left: -10, right: 0, bottom: 0},
  1253.     viewJustify: 8402948,
  1254.     _proto: protoStaticText,
  1255.     debug: "amountLabel"
  1256.    };
  1257.  
  1258.  
  1259.  
  1260. ckPayee := /* child of checkView */
  1261.    {viewBounds: {top: 10, left: 2, right: -2, bottom: 40},
  1262.     viewJustify: 8396848,
  1263.     viewFlags: 14849,
  1264.     _proto: protoInputLine,
  1265.     debug: "ckPayee"
  1266.    };
  1267. // View ckPayee is declared to checkView
  1268.  
  1269.  
  1270.  
  1271. payeeLabel := /* child of checkView */
  1272.    {text: "Payee",
  1273.     viewBounds: {top: -10, left: 0, right: 50, bottom: 15},
  1274.     viewJustify: 8398848
  1275.     ,
  1276.     _proto: protoStaticText,
  1277.     debug: "payeeLabel"
  1278.    };
  1279.  
  1280.  
  1281.  
  1282. ckMemo := /* child of checkView */
  1283.    {viewBounds: {top: 0, left: 2, right: -120, bottom: 25},
  1284.     viewJustify: 8396848,
  1285.     viewFlags: 14849,
  1286.     _proto: protoInputLine,
  1287.     debug: "ckMemo"
  1288.    };
  1289. // View ckMemo is declared to checkView
  1290.  
  1291.  
  1292.  
  1293. memoLabel := /* child of checkView */
  1294.    {text: "Memo",
  1295.     viewBounds: {top: -5, left: 0, right: 50, bottom: 10},
  1296.     viewJustify: 8398848,
  1297.     _proto: protoStaticText,
  1298.     debug: "memoLabel"
  1299.    };
  1300.  
  1301.  
  1302.  
  1303. name := /* child of checkView */
  1304.    {text: "Static Text",
  1305.     viewBounds: {left: 5, top: 2, right: 120, bottom: 14},
  1306.     viewSetupFormScript:
  1307.       func()
  1308.       begin
  1309.          self.text := userConfiguration.name;
  1310.       end,
  1311.     _proto: protoStaticText,
  1312.     debug: "name"
  1313.    };
  1314.  
  1315.  
  1316.  
  1317. address := /* child of checkView */
  1318.    {text: "Static Text",
  1319.     viewBounds: {left: 0, top: 0, right: 0, bottom: 12},
  1320.     viewJustify: 8398336,
  1321.     viewSetupFormScript:
  1322.       func()
  1323.       begin
  1324.          self.text := userConfiguration.address;
  1325.       end,
  1326.     _proto: protoStaticText,
  1327.     debug: "address"
  1328.    };
  1329.  
  1330.  
  1331.  
  1332. cityState := /* child of checkView */
  1333.    {text: "Static Text",
  1334.     viewBounds: {left: 0, top: 0, right: 0, bottom: 12},
  1335.     viewJustify: 8398336,
  1336.     viewSetupFormScript:
  1337.       func()
  1338.       begin
  1339.          self.text := userConfiguration.cityZip;
  1340.       end,
  1341.     _proto: protoStaticText,
  1342.     debug: "cityState"
  1343.    };
  1344.  
  1345.  
  1346.  
  1347.  
  1348. // ---- Back in File mainlayout.t ----
  1349.  
  1350. // ---- File overview.t ----
  1351. overview := /* child of checkBook */
  1352.    {viewFlags: 0,
  1353.     viewFormat: 256,
  1354.     viewBounds: {top: 15, left: 1, right: -1, bottom: -22},
  1355.     viewJustify: 240,
  1356.     DisplayFromCursor:
  1357.       func()
  1358.       begin
  1359.          :FillRows();
  1360.          :Dirty();
  1361.       end,
  1362.     viewEffect: 1023009,
  1363.     viewShowScript:
  1364.       func()
  1365.       begin
  1366.          currentView := self;   // currentView is in the base view
  1367.       
  1368.          target := nil;   // no current soup entry displayed.
  1369.       end,
  1370.     viewSetupDoneScript:
  1371.       func()
  1372.       begin
  1373.          :DisplayFromCursor();
  1374.          currentView := self;   // currentView is in the base view
  1375.       
  1376.          target := nil;   // no current soup entry displayed.
  1377.       end,
  1378.     viewSetupChildrenScript:
  1379.       func()
  1380.       begin
  1381.          // called before this view's children are created.
  1382.          local rowHeight := pt_cbEntryProto.viewBounds.bottom;
  1383.          local viewHeight := :LocalBox().bottom;
  1384.          self.numberRows := viewHeight div rowHeight;
  1385.       
  1386.          // resize to be an even multiple of the rowHeight (+1 for the line at the
  1387.          // bottom of each row). This way, ScrollEffect can scroll correctly.
  1388.          local newBounds := Clone(viewBounds);
  1389.          newBounds.bottom := viewBounds.bottom - (viewHeight - numberRows * rowHeight);
  1390.          SetValue(self, 'viewBounds, newBounds);
  1391.       
  1392.        
  1393.          // stepChildren is an array of cbEntryProto templates.
  1394.          // self is required here since the stepChildren slot doesn't exist
  1395.          // for a template with no children.
  1396.          self.stepChildren := Array(numberRows, pt_cbEntryProto);
  1397.       end,
  1398.     numberRows: nil,
  1399.     FillRows:
  1400.       func()
  1401.       begin
  1402.          // fill rows from the soup starting at the current cursor position
  1403.       
  1404.          // make a copy of checkBookCursor so we don't change it's location
  1405.          // in the soup
  1406.          local cursorCopy := checkBookCursor:Clone();
  1407.          
  1408.          // Fill rows from the cursor in each cbEntryProto child view
  1409.          foreach child in :ChildViewFrames() do begin
  1410.             child:FillFromCheck(cursorCopy:Entry());
  1411.             cursorCopy:Next();
  1412.          end;
  1413.       end,
  1414.     DoScroll:
  1415.       func(scrollUp)
  1416.       begin
  1417.          // This method is called by ScrollEffect from ScrollDown or ScrollUp.
  1418.          :FillRows();
  1419.       
  1420.          // dirty the children which were just scrolled in.
  1421.          local start;
  1422.          local finish;
  1423.       
  1424.          local children := :ChildViewFrames();
  1425.          if scrollUp then begin
  1426.             start := 0;
  1427.             finish := :NumberRowsToScroll() - 1;
  1428.          end else begin
  1429.             start := Length(children) - :NumberRowsToScroll();
  1430.             finish := Length(children) - 1;
  1431.          end;
  1432.       
  1433.          for i := start to finish do
  1434.             children[i]:Dirty();
  1435.       end;,
  1436.     NumberRowsToScroll:
  1437.       func()
  1438.       begin
  1439.          return Max(1, numberRows div 2);
  1440.       end,
  1441.     viewSetupFormScript:
  1442.       func()
  1443.       begin
  1444.       end,
  1445.     viewScrollDownScript:
  1446.       func()
  1447.       begin
  1448.          if not checkbookCursor:Clone():Move(numberRows) then begin
  1449.             // there are no more checks beyond what is now visible
  1450.             GetRoot():SysBeep();
  1451.          end else begin
  1452.             local numToScroll := :NumberRowsToScroll();
  1453.             checkbookCursor:Move(numToScroll);
  1454.             :SlideEffect(-numToScroll * pt_CBEntryProto.viewBounds.bottom,
  1455.                0,
  1456.                scrollDownSound,
  1457.                'DoScroll,
  1458.                [nil]
  1459.             );
  1460.          end;
  1461.       end,
  1462.     viewScrollUpScript:
  1463.       func()
  1464.       begin
  1465.          if not checkbookCursor:Clone():Prev() then begin
  1466.             // there are no more checks beyond what is now visible
  1467.             GetRoot():SysBeep();
  1468.          end else begin
  1469.             local numToScroll := :NumberRowsToScroll();
  1470.             checkbookCursor:Move(-numToScroll);
  1471.             if not checkbookCursor:Entry() then
  1472.                checkbookCursor:Next();
  1473.             :SlideEffect(numToScroll * pt_CBEntryProto.viewBounds.bottom,
  1474.                0,
  1475.                scrollUpSound,
  1476.                'DoScroll,
  1477.                [true]
  1478.             );
  1479.          end;
  1480.       end,
  1481.     viewclass: 74,
  1482.     debug: "overview"
  1483.    };
  1484. // View overview is declared to checkBook
  1485.  
  1486.  
  1487. // ---- Back in File mainlayout.t ----
  1488.  
  1489.  
  1490. // ---- Beginning of non-used User Protos ----
  1491.  
  1492. // ---- File assistDialogProto ----
  1493. asistDialog :=
  1494.    {viewBounds: {left: 0, top: 0, right: 194, bottom: 144},
  1495.     applicationWasOpen:
  1496.       nil   // true if the application was open before the user used IA,
  1497.     DisplayEntry:
  1498.       func(anEntry, appWasOpen)
  1499.       begin
  1500.          self.applicationWasOpen := appWasOpen;
  1501.       
  1502.          SetValue(assistDate.entryLine, 'text, ShortDateStr(anEntry.date, 0));
  1503.          SetValue(assistAmount.entryLine, 'text, FormattedNumberStr(anEntry.amount, "%0.2f"));
  1504.         
  1505.          local names := :GetPayeeNames(anEntry.payee);
  1506.          assistPayee:SetLabelCommands(names);
  1507.          if names then
  1508.             SetValue(assistPayee.entryLine, 'text, names[0]);
  1509.          else
  1510.             SetValue(assistPayee.entryLine, 'text, "");
  1511.       
  1512.          self.entry := anEntry;
  1513.       end,
  1514.     SaveEntry:
  1515.       func()
  1516.       begin
  1517.          local newCheck := entry;
  1518.          local value;
  1519.       
  1520.          value := StringToDate(assistDate.text);
  1521.          if value then
  1522.             // convert to 12:00 AM by truncating any minutes beyond 12 AM
  1523.             newCheck.date := value - value MOD kMinutesPerDay;
  1524.       
  1525.          newCheck.payee := assistPayee.entryLine.text;
  1526.       
  1527.          value := StringToNumber(assistAmount.entryLine.text);
  1528.          if value then
  1529.             newCheck.amount := value;
  1530.       
  1531.          GetRoot().(kAppSymbol):AddCheckToSoup(newCheck);
  1532.       end,
  1533.     viewJustify: 80,
  1534.     entry: nil,
  1535.     GetPayeeNames:
  1536.       func(aName)
  1537.       begin
  1538.          // returns an array of strings matching the input string (from the
  1539.          // Name soup)
  1540.       
  1541.          // SmartCFQuery("") causes an exception
  1542.          if StrLen(aName) = 0 then
  1543.             return nil;
  1544.          
  1545.          local cfEntries := SmartCFQuery(aName);
  1546.          if not cfEntries then
  1547.             return nil;
  1548.       
  1549.          return foreach cfEntry in cfEntries collect begin
  1550.             if cfEntry.name exists then
  1551.                cfEntry.name.first && cfEntry.name.last;
  1552.             else
  1553.                cfEntry.company;
  1554.          end;
  1555.       end,
  1556.     _proto: protoFloater,
  1557.     debug: "asistDialog"
  1558.    };
  1559.  
  1560. _view003 := /* child of asistDialog */
  1561.    {
  1562.     buttonClickScript:
  1563.       func()
  1564.       begin
  1565.          inherited:buttonClickScript();   // close this floater.
  1566.          if not applicationWasOpen then
  1567.             GetRoot().(kAppSymbol):Close();  // close the application
  1568.       end,
  1569.     _proto: protoLargeClosebox
  1570.    };
  1571.  
  1572.  
  1573.  
  1574. _view004 := /* child of asistDialog */
  1575.    {text: "Pay",
  1576.     buttonClickScript:
  1577.       func()
  1578.       begin
  1579.          :Parent():SaveEntry();
  1580.          base:Close();
  1581.       end,
  1582.     viewBounds: {top: 0, left: -32, right: -6, bottom: 0},
  1583.     viewJustify: 8402950,
  1584.     _proto: protoTextButton
  1585.    };
  1586.  
  1587.  
  1588.  
  1589. assistDate := /* child of asistDialog */
  1590.    {viewBounds: {left: 14, top: 26, right: 190, bottom: 48},
  1591.     label: "Date:",
  1592.     _proto: protoLabelInputLine,
  1593.     debug: "assistDate"
  1594.    };
  1595. // View assistDate is declared to asistDialog
  1596.  
  1597.  
  1598.  
  1599. assistPayee := /* child of asistDialog */
  1600.    {viewBounds: {left: 14, top: 10, right: 190, bottom: 32},
  1601.     viewJustify: 8396800,
  1602.     labelCommands: [],
  1603.     label: "To:",
  1604.     _proto: protoLabelInputLine,
  1605.     debug: "assistPayee"
  1606.    };
  1607. // View assistPayee is declared to asistDialog
  1608.  
  1609.  
  1610.  
  1611. assistAmount := /* child of asistDialog */
  1612.    {viewBounds: {left: 14, top: 10, right: 190, bottom: 32},
  1613.     viewJustify: 8396800,
  1614.     label: "$:",
  1615.     _proto: protoLabelInputLine,
  1616.     debug: "assistAmount"
  1617.    };
  1618. // View assistAmount is declared to asistDialog
  1619.  
  1620.  
  1621.  
  1622.  
  1623. // ---- File cbEntryProto ----
  1624. container :=
  1625.    {viewFlags: 513,
  1626.     viewFormat: 337,
  1627.     viewBounds: {top: 0, left: 1, right: -1, bottom: 20},
  1628.     viewJustify: 8240,
  1629.     currentCheck: nil,
  1630.     viewClickScript:
  1631.       func(unit)
  1632.       begin
  1633.          // when user clicks on a check in the overview, ask the
  1634.          // base view to display that check.
  1635.          if currentCheck then begin
  1636.             InkOff(unit);
  1637.             :Hilite(true); // turn on hiliting
  1638.             GetRoot().(kAppSymbol):DisplayCheck(currentCheck);
  1639.             :Hilite(nil);   // turn off the hiliting.
  1640.             return true;
  1641.          end
  1642.          else
  1643.             return nil;
  1644.       end,
  1645.     FillFromCheck:
  1646.       func(check)
  1647.       begin
  1648.          // Fill static texts in the overview
  1649.          // if there are no entries it displays empty strings in the static texts
  1650.          // Doesn't use SetValue because we want to dirty by hand (for scrolling
  1651.          // to avoid unnecessary redraw).
  1652.          if check <> nil then begin
  1653.             ovDate.text := ShortDateStr(check.date, 0);
  1654.             ovNumber.text := NumberStr(check.number);
  1655.             ovPayee.text := check.payee;
  1656.             ovAmount.text := FormattedNumberStr((check.amount), "%0.2f");
  1657.          end
  1658.          else begin
  1659.             ovDate.text := "";
  1660.             ovNumber.text := "";
  1661.             ovPayee.text := "";
  1662.             ovAmount.text := "";
  1663.          end;
  1664.       
  1665.          self.currentCheck := check;
  1666.       end;,
  1667.     viewclass: 74,
  1668.     debug: "container"
  1669.    };
  1670.  
  1671. ovDate := /* child of container */
  1672.    {text: "10/15/93",
  1673.     viewBounds: {left: 0, top: 0, right: 55, bottom: 0},
  1674.     viewJustify: 8388804,
  1675.     _proto: protoStaticText,
  1676.     debug: "ovDate"
  1677.    };
  1678. // View ovDate is declared to container
  1679.  
  1680.  
  1681.  
  1682. ovNumber := /* child of container */
  1683.    {text: "232",
  1684.     viewBounds: {left: 0, top: 0, right: 30, bottom: 0},
  1685.     viewJustify: 8389829,
  1686.     _proto: protoStaticText,
  1687.     debug: "ovNumber"
  1688.    };
  1689. // View ovNumber is declared to container
  1690.  
  1691.  
  1692.  
  1693. ovPayee := /* child of container */
  1694.    {text: "Julie McKeehan",
  1695.     viewBounds: {top: 0, left: 90, right: -57, bottom: 0},
  1696.     viewJustify: 8388852,
  1697.     _proto: protoStaticText,
  1698.     debug: "ovPayee"
  1699.    };
  1700. // View ovPayee is declared to container
  1701.  
  1702.  
  1703.  
  1704. ovAmount := /* child of container */
  1705.    {text: "12322.56",
  1706.     viewBounds: {left: 0, top: 0, right: 57, bottom: 0},
  1707.     viewJustify: 8389829,
  1708.     _proto: protoStaticText,
  1709.     debug: "ovAmount"
  1710.    };
  1711. // View ovAmount is declared to container
  1712.  
  1713.  
  1714.  
  1715.  
  1716. // ---- End of non-used User Protos ----
  1717.  
  1718.  
  1719.  
  1720. // ---- Beginning of section for non used Layout files ----
  1721.  
  1722. // ---- File checkView.t ----
  1723. checkView :=
  1724.    {viewFlags: 0,
  1725.     viewFormat: 336,
  1726.     viewBounds: {top: 80, left: 4, right: -4, bottom: 230},
  1727.     viewJustify: 48,
  1728.     DisplayCheck:
  1729.       func(check)
  1730.       begin
  1731.          //displays a check in the checkView
  1732.       
  1733.          // save the previous entry
  1734.          if currentCheck then
  1735.             :SaveCheck();
  1736.       
  1737.          SetValue(ckDate, 'text, ShortDateStr(check.date, 0));
  1738.          SetValue(ckNumber, 'text, NumberStr(check.number));
  1739.          SetValue(ckPayee, 'text, check.payee);
  1740.          SetValue(ckAmount, 'text, FormattedNumberStr((check.amount), "%0.2f"));
  1741.          SetValue(ckMemo, 'text, check.memo);
  1742.       
  1743.          self.currentCheck := check;
  1744.          target := check; // current soup entry. Used for routing and filing.
  1745.                           // target is a slot in the base view.
  1746.       end;,
  1747.     currentCheck: nil,
  1748.     SaveCheck:
  1749.       func()
  1750.       begin
  1751.           if currentCheck then
  1752.           begin
  1753.               // reads the information from the input lines into the current
  1754.               // check and saves the entry into the soup.
  1755.               
  1756.               currentCheck.payee := ckPayee.text;
  1757.               currentCheck.memo := ckMemo.text;
  1758.               
  1759.               // StringToNumber can return NIL if the string is not a valid number
  1760.               // It would be a bad idea to have a NIL amount, or number.
  1761.               local value := StringToNumber(ckNumber.text);
  1762.               if value then begin
  1763.                  // RIntToL converts a real to an integer
  1764.                  currentCheck.number := RIntToL(value);
  1765.               end;
  1766.               
  1767.               value := StringToNumber(ckAmount.text);
  1768.               if value then
  1769.                  currentCheck.amount := value;
  1770.               
  1771.               // StringToDate takes into account the current time.
  1772.               // thus, if the current time is 7:03 PM
  1773.               // StringToDate("5/5/93") returns number of minutes to 7:03 PM
  1774.               // on 5/5/93.
  1775.               // StringToDate can return NIL for an invalid date.
  1776.               value := StringToDate(ckDate.text);
  1777.               if value then
  1778.                  // convert to 12:00 AM by truncating any minutes beyond 12 AM
  1779.                  currentCheck.date := value - value mod kMinutesPerDay;
  1780.               
  1781.               EntryChange(currentCheck);   // save in the soup
  1782.               self.currentCheck := nil;
  1783.           end;
  1784.       end,
  1785.     viewEffect: 1023009,
  1786.     viewShowScript:
  1787.       func()
  1788.       begin
  1789.          currentView := self;   // currentView is in the base view
  1790.       end,
  1791.     viewHideScript:
  1792.       func()
  1793.       begin
  1794.          :SaveCheck();
  1795.       end,
  1796.     DeleteCheck:
  1797.       func(entryToDelete)
  1798.       begin
  1799.          EntryRemoveFromSoup(entryToDelete);
  1800.          currentCheck := target := nil;
  1801.          checkBookCursor:Next();
  1802.          if not checkBookCursor:Entry() then // they deleted the last entry in the soup
  1803.             checkBookCursor:Prev();
  1804.          if not checkBookCursor:Entry() then begin// there are no more books in the soup
  1805.             GetRoot().(kAppSymbol):DisplayOverview();
  1806.          end
  1807.          else
  1808.             GetRoot().(kAppSymbol):DisplayCurrentCheck();
  1809.       end     ,
  1810.     viewScrollDownScript:
  1811.       func()
  1812.       begin
  1813.          local cursor := checkbookCursor;
  1814.       
  1815.          cursor:Next();
  1816.       
  1817.          local entry := cursor:Entry();
  1818.          if entry = nil then begin
  1819.             GetRoot():SysBeep();   
  1820.             cursor:Prev();
  1821.          end else begin
  1822.             local bounds := :LocalBox();
  1823.             :SlideEffect(- (bounds.bottom - bounds.top),
  1824.                0,
  1825.                scrollDownSound,
  1826.                'DisplayCheck,
  1827.                [entry]
  1828.             );
  1829.          end;
  1830.       end,
  1831.     viewScrollUpScript:
  1832.       func()
  1833.       begin
  1834.          local cursor := checkbookCursor;
  1835.       
  1836.          cursor:Prev();
  1837.       
  1838.          local entry := cursor:Entry();
  1839.          if entry = nil then begin
  1840.             GetRoot():SysBeep();   
  1841.             cursor:Next();
  1842.          end else begin
  1843.             local bounds := :LocalBox();
  1844.             :SlideEffect(bounds.bottom - bounds.top,
  1845.                0,
  1846.                scrollUpSound,
  1847.                'DisplayCheck,
  1848.                [entry]
  1849.             );
  1850.          end;
  1851.       end,
  1852.     viewclass: 74,
  1853.     debug: "checkView"
  1854.    };
  1855.  
  1856. ckNumber := /* child of checkView */
  1857.    {viewBounds: {top: 10, left: -60, right: -2, bottom: 35},
  1858.     viewJustify: 8388640,
  1859.     viewFlags: 10753,
  1860.     _proto: protoInputLine,
  1861.     debug: "ckNumber"
  1862.    };
  1863. // View ckNumber is declared to checkView
  1864.  
  1865.  
  1866.  
  1867. ckDate := /* child of checkView */
  1868.    {viewBounds: {top: 0, left: -90, right: -2, bottom: 30},
  1869.     viewJustify: 8396832,
  1870.     viewFlags: 67648033,
  1871.     _proto: protoInputLine,
  1872.     debug: "ckDate"
  1873.    };
  1874. // View ckDate is declared to checkView
  1875.  
  1876.  
  1877.  
  1878. ckAmount := /* child of checkView */
  1879.    {viewBounds: {top: 0, left: 12, right: -97, bottom: 0},
  1880.     viewJustify: 8400944,
  1881.     viewFlags: 10753,
  1882.     _proto: protoInputLine,
  1883.     debug: "ckAmount"
  1884.    };
  1885. // View ckAmount is declared to checkView
  1886.  
  1887.  
  1888.  
  1889. amountLabel := /* child of checkView */
  1890.    {text: "$",
  1891.     viewBounds: {top: 0, left: -10, right: 0, bottom: 0},
  1892.     viewJustify: 8402948,
  1893.     _proto: protoStaticText,
  1894.     debug: "amountLabel"
  1895.    };
  1896.  
  1897.  
  1898.  
  1899. ckPayee := /* child of checkView */
  1900.    {viewBounds: {top: 10, left: 2, right: -2, bottom: 40},
  1901.     viewJustify: 8396848,
  1902.     viewFlags: 14849,
  1903.     _proto: protoInputLine,
  1904.     debug: "ckPayee"
  1905.    };
  1906. // View ckPayee is declared to checkView
  1907.  
  1908.  
  1909.  
  1910. payeeLabel := /* child of checkView */
  1911.    {text: "Payee",
  1912.     viewBounds: {top: -10, left: 0, right: 50, bottom: 15},
  1913.     viewJustify: 8398848
  1914.     ,
  1915.     _proto: protoStaticText,
  1916.     debug: "payeeLabel"
  1917.    };
  1918.  
  1919.  
  1920.  
  1921. ckMemo := /* child of checkView */
  1922.    {viewBounds: {top: 0, left: 2, right: -120, bottom: 25},
  1923.     viewJustify: 8396848,
  1924.     viewFlags: 14849,
  1925.     _proto: protoInputLine,
  1926.     debug: "ckMemo"
  1927.    };
  1928. // View ckMemo is declared to checkView
  1929.  
  1930.  
  1931.  
  1932. memoLabel := /* child of checkView */
  1933.    {text: "Memo",
  1934.     viewBounds: {top: -5, left: 0, right: 50, bottom: 10},
  1935.     viewJustify: 8398848,
  1936.     _proto: protoStaticText,
  1937.     debug: "memoLabel"
  1938.    };
  1939.  
  1940.  
  1941.  
  1942. name := /* child of checkView */
  1943.    {text: "Static Text",
  1944.     viewBounds: {left: 5, top: 2, right: 120, bottom: 14},
  1945.     viewSetupFormScript:
  1946.       func()
  1947.       begin
  1948.          self.text := userConfiguration.name;
  1949.       end,
  1950.     _proto: protoStaticText,
  1951.     debug: "name"
  1952.    };
  1953.  
  1954.  
  1955.  
  1956. address := /* child of checkView */
  1957.    {text: "Static Text",
  1958.     viewBounds: {left: 0, top: 0, right: 0, bottom: 12},
  1959.     viewJustify: 8398336,
  1960.     viewSetupFormScript:
  1961.       func()
  1962.       begin
  1963.          self.text := userConfiguration.address;
  1964.       end,
  1965.     _proto: protoStaticText,
  1966.     debug: "address"
  1967.    };
  1968.  
  1969.  
  1970.  
  1971. cityState := /* child of checkView */
  1972.    {text: "Static Text",
  1973.     viewBounds: {left: 0, top: 0, right: 0, bottom: 12},
  1974.     viewJustify: 8398336,
  1975.     viewSetupFormScript:
  1976.       func()
  1977.       begin
  1978.          self.text := userConfiguration.cityZip;
  1979.       end,
  1980.     _proto: protoStaticText,
  1981.     debug: "cityState"
  1982.    };
  1983.  
  1984.  
  1985.  
  1986.  
  1987. // End of output